package com.chagee.store.operation.server.service.biz;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.alibaba.fastjson.*;
import com.chagee.store.operation.common.constant.CommonConstant;
import com.chagee.store.operation.common.exception.BizErrorCode;
import com.chagee.store.operation.common.exception.BizException;
import com.chagee.store.operation.server.model.bo.InvoiceDetailBO;
import com.chagee.store.operation.server.model.response.FinanceResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author : hk
 * @Date : 2025/1/9
 */

@Slf4j
@Service
@RequiredArgsConstructor
public class FinanceBizService {

	@Value("${finance.host}")
	private String host;
	@Value("${finance.url}")
	private String url;
	@Value("${finance.secretKey}")
	private String secretKey;


	public void pushInvoiceDetail(InvoiceDetailBO invoiceDetailBO) {

		log.info("FinanceBizService_pushInvoiceDetail_invoiceDetail:{}", JSON.toJSON(invoiceDetailBO));

		Map<String, String> hashMap = new HashMap<>();
		hashMap.put("host", host);
		String requestUrl = StrUtil.format(url, hashMap);

		long timestamp = System.currentTimeMillis() / 1000;
		log.info("timestamp:{}",timestamp);
		JSONObject jsonObject = JSONObject.parseObject(JSON.toJSONString(invoiceDetailBO));
		log.info("jsonObject:{}", JSONObject.toJSONString(jsonObject));
		String sign = generateSignature(jsonObject, secretKey, timestamp);
		log.info("sign:{}",sign);
		try (HttpResponse execute = HttpRequest.post(requestUrl)
			.header("timestamp", timestamp + "")
			.header("signature", sign)
			.contentType("application/json")
			.body(jsonObject.toJSONString())
			.execute()) {
			String body = execute.body();

			log.info("结算单{}发票信息推送财务返回: {}", invoiceDetailBO.getBillNo(), body);

			FinanceResponse financeResponse = JSON.parseObject(body, new TypeReference<FinanceResponse>() {});
			if (CommonConstant.NOT_DELETE_FLAG.equals(financeResponse.getCode())) {
				log.info("结算单{}发票信息推送财务成功", invoiceDetailBO.getBillNo());
			}else {
				log.error("结算单{}发票信息推送财务失败", invoiceDetailBO.getBillNo());
				throw new BizException(BizErrorCode.PUSH_FINANCE_ERROR);
			}
		}

	}

	/**
	 * 生产签名
	 *
	 * @param params    接口参数
	 * @param secretKey 密钥
	 * @param timestamp 时间戳 秒级
	 * @return signature
	 */
	public static String generateSignature(Map<String, Object> params, String secretKey, long timestamp) {
		// 对参数进行排序
		Map<String, Object> sortedParams = sortMap(params);
		sortedParams.put("timestamp", timestamp);
		// 拼接参数
		StringBuilder paramBuilder = new StringBuilder();
		for (Map.Entry<String, Object> entry : sortedParams.entrySet()) {
			paramBuilder.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
		}
		if (paramBuilder.length() > 0) {
			paramBuilder.setLength(paramBuilder.length() - 1); // 去掉最后一个&
		}
		// 拼接密钥
		paramBuilder.append(secretKey);

		// 使用MD5算法生成签名
		return DigestUtils.md5Hex(paramBuilder.toString());
	}

	public static Map<String, Object> sortMap(Map<String, Object> map) {
		Map<String, Object> sortedMap = new TreeMap<>();
		map.forEach((key, value) -> {
			if (value instanceof Map) {
				sortedMap.put(key, sortMap((Map<String, Object>) value));
			} else if (value instanceof Collection) {
				sortedMap.put(key, sortList(new ArrayList<>((List<Object>) value)));
			} else {
				sortedMap.put(key, value);
			}
		});
		return sortedMap;
	}

	public static List<Object> sortList(List<Object> sortedList) {
		if (CollectionUtil.isEmpty(sortedList)) {
			return sortedList;
		}
		return sortedList.stream().map(item -> {
			if (item instanceof Map) {
				return sortMap((Map<String, Object>) item);
			} else if (item instanceof Collection) {
				return sortList((List<Object>) item);
			}
			return item;
		}).collect(Collectors.toList());
	}

	/**
	 * 签名校验
	 *
	 * @param params    接口参数
	 * @param secretKey 密钥
	 * @param signature 签名
	 * @param timestamp 时间戳 秒级
	 * @return true:通过 false:不通过
	 */
	public static boolean verifySignature(Map<String, Object> params, String secretKey, String signature,
										  long timestamp) {
		String generatedSign = generateSignature(params, secretKey, timestamp);
		return generatedSign.equals(signature);
	}


}
